"""API 我们定义了一个与身份验证相关的依赖函数."""
from typing_extensions import Annotated

from fastapi import Depends, Form, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from jwt import ExpiredSignatureError, InvalidTokenError
from sqlalchemy.sql import select

from core.database import db_session

from core.models import Member
from api.settings import api_settings
from api.v1.models import MemberRefreshToken
from api.v1.auth.jwt import JWT
from api.v1.service.member import MemberServiceAPI


def authenticate_member(
    service: Annotated[MemberServiceAPI, Depends()],
    form: Annotated[OAuth2PasswordRequestForm, Depends()]
) -> Member:
    """我们执行会员身份验证.

    Args:
        service (Annotated[MemberServiceAPI, Depends]): 会员服务
        form_data (Annotated[OAuth2PasswordRequestForm, Depends): 

    Raises:
        HTTPException: 成员身份验证失败时发生的异常

    Returns:
        Member: 成员对象
    """
    return service.authenticate_member(form.username, form.password)


def authenticate_refresh_token(
    db: db_session,
    refresh_token: Annotated[str, Form(...)]
) -> str:
    """refresh Token验证.

    Args:
        db (db_session): 数据库会话
        refresh_token (Annotated[str, Form(...)]): refresh Token

    Raises:
        credentials_exception: 在数据库中 refresh Token当您找不到时发生的异常
        credentials_exception: refresh Token过期时发生的异常
        credentials_exception: refresh Token无效时发生的异常

    Returns:
        MemberRefreshToken: refresh Token 对象
    """
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Invalid refresh token",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        # Totin验证  这里如果不能验证通过就会出现raise 
        JWT.decode_token(refresh_token, api_settings.REFRESH_TOKEN_SECRET_KEY)

        member_refresh_token = db.scalar(
            select(MemberRefreshToken)
            .where(MemberRefreshToken.refresh_token == refresh_token)
        )
        if not member_refresh_token:
            raise credentials_exception

        return member_refresh_token

    except ExpiredSignatureError as e:
        credentials_exception.detail = "Refresh Token has expired"
        raise credentials_exception from e
    except InvalidTokenError as e:
        credentials_exception.detail = "Could not validate credentials"
        raise credentials_exception from e
